﻿--[[
@brief      通用的浏览器组件
@date       2017-02-26
@author     jameszhai
]]

EWebError = 
{
    erNoError  = 0;
    erWebCrash = 1;
    erOpenFail = 2;
};

EWebUIConst = 
{
    nHorzSize = 34;
    nVertSize = 72;

    nCloseWait= 100;            -- 等待100毫秒关闭浏览器

    FB_SUCCEESS_WEB_URL = LoadStr("FACEBOOK_SUCCESS_URL");
    
    LOGIN_ERR_MSG_REGISTER = LoadStr("FACEBOOK_REGISTER_ERROR_TIPS");
};

TBrowserView = 
{
    sFBWebURL = nil;

    -- 加载播放器
    InitBrowser = function()
    end;

    -- 卸载播放器
    UnInitBrowser = function()
        TBrowserView.DestroyUI();
    end;

    -- 打开的回调
    SetEvtSink = function(sOnOpen, sOnClose, sOnError)
        TBrowserView.sOnOpen  = sOnOpen;
        TBrowserView.sOnClose = sOnClose;
        TBrowserView.sOnError = sOnError;
    end;

    -- 显示浏览器
    ShowView = function(sWebUrl, zParam)
        TGPLog.LogI("VideoView", "Try to open URL: " .. sWebUrl);

        if TBrowserView.CreateUI(zParam) then
            -- 打开网页
            TBrowserView.StartWeb(sWebUrl);

            -- 先隐藏
            TBrowserView.pWebView:Show(false);
            TBrowserView.bIsOpen = false;
            if nil ~= zParam and nil ~= zParam["canWebClose"] then
                TBrowserView.canWebClose = zParam["canWebClose"]
            end;

            -- 显示等待界面
            if nil ~= zParam and nil ~= zParam["showLoading"] and 
               tostring(zParam["showLoading"]) == "1" then
                TBrowserView.ShowWaitUI(true);
            else
                TBrowserView.ShowWaitUI(false);
            end;

            -- 显示
            local   pThis  = ui_utility.get_ctrl_ptr_by_id(TBrowserView.dwViewID);

            if nil ~= pThis then
                pThis:Restore();

                if nil ~= zParam and (nil ~= zParam["alwaysOnTop"]) and 
                   tostring(zParam["alwaysOnTop"]) == "0" then
                    ui_utility.setproperty_by_id(TBrowserView.dwViewID, "AlwaysOnTop",
                                                 tostring("false"));
                else
                    ui_utility.setproperty_by_id(TBrowserView.dwViewID, "AlwaysOnTop",
                                                 tostring("true"));
                end;

                -- 移动浏览器
                TBrowserView.MoveBrowser(pThis, zParam);

                pThis:MoveToCenter();
                pThis:BringToTop();

                pThis:Show(TRUE);
                pThis:SetFocus();

                TBrowserView.bVisible = true;

                TBrowserView.NotifyOpen(0);
                return  true;
            else
                TGPLog.LogE("Browser", "Video control is nil.");
                TBrowserView.NotifyOpen(-2);
            end;
        else
            TGPLog.LogE("Browser", "Web browser is nil.");
            TBrowserView.NotifyOpen(-3);
        end;

        return  false;
    end;

    -- 隐藏播放器
    HideView = function()
        -- 关闭WebBrowser
        if (TBrowserView.IsValidID(TBrowserView.dwViewID)) and TBrowserView.bVisible then
            TBrowserView.bVisible = false;

            -- 关闭视频
            TBrowserView.StopWeb();

            -- 隐藏界面
            ui_utility.show_ctrl(TBrowserView.dwViewID, false);
        end;
    end;

    -- 移动窗口
    MoveBrowser = function(pThis, zParam)
        if nil ~= zParam then
            local   rtTemp = pThis:GetRectEx(FALSE,TRUE);
            local   bChange = false;

            if (nil ~= zParam["Width"]) then
                bChange = true;
                rtTemp.right  = rtTemp.left + tonumber(zParam["Width"]) + EWebUIConst.nHorzSize;
            end;

            if (nil ~= zParam["Height"]) then
                bChange = true;
                rtTemp.bottom = rtTemp.top  + tonumber(zParam["Height"]) + EWebUIConst.nVertSize;
            end;

            if (bChange) then
                pThis:MoveEx(rtTemp,TRUE);
            end;

            if nil ~= zParam["Title"] then
                local dwTemp = ui_utility.get_ctrl_id_by_path(pThis:GetControlID(), 
                                                              "TitleBarCtn\\lblTitle");
                if (TBrowserView.IsValidID(dwTemp)) then
                    ui_utility.setproperty_by_id(dwTemp, "Caption", zParam["Title"]);
                end;
            end;

            if (nil ~= zParam["FixSize"]) and (zParam["FixSize"]) then
                ui_utility.setproperty_by_id(TBrowserView.dwViewID, "SizeBox",
                                             tostring("false"));
            else
                ui_utility.setproperty_by_id(TBrowserView.dwViewID, "SizeBox",
                                             tostring("true"));

                if (nil ~= zParam["MinWidth"]) then
                    ui_utility.setproperty_by_id(TBrowserView.dwViewID, "MinWidth",
                        tostring(EWebUIConst.nHorzSize + tonumber(zParam["MinWidth"])));
                end;

                if (nil ~= zParam["MinHeight"]) then
                    ui_utility.setproperty_by_id(TBrowserView.dwViewID, "MinHeight",
                        tostring(EWebUIConst.nVertSize + tonumber(zParam["MinHeight"])));
                end;

                if (nil ~= zParam["MaxWidth"]) then
                    ui_utility.setproperty_by_id(TBrowserView.dwViewID, "MaxWidth",
                        tostring(EWebUIConst.nHorzSize + tonumber(zParam["MaxWidth"])));
                end;

                if (nil ~= zParam["MaxHeight"]) then
                    ui_utility.setproperty_by_id(TBrowserView.dwViewID, "MaxHeight",
                        tostring(EWebUIConst.nVertSize + tonumber(zParam["MaxHeight"])));
                end;
            end;
        end;
    end;

    -- 开始Navigate
    OnStartOpen = function(pUILib, sWebUrl, dwCtrlID)
        TGPLog.LogI("VideoView", "Start open url: " .. sWebUrl);

        if (nil ~= TBrowserView.pWebView) then
            TBrowserView.pWebView:Show(false);
            TBrowserView.bIsOpen = false;

            if string.find(sWebUrl, "https://www.facebook.com/r.php") ~= nil then
                TBrowserView.pWebView:Stop();
                local z_param = {};
                z_param["errmsg" ] = EWebUIConst.LOGIN_ERR_MSG_REGISTER;
                comm_center.call_service("SvrShowFBLoginFailed", z_param);
            elseif string.find(sWebUrl, "https://www.facebook.com/confirmemail.php") ~= nil then
                TBrowserView.pWebView:Stop();
                local z_param = {};
                z_param["errmsg" ] = LoadStr("FACEBOOK_ACTIVE_ERROR_TIPS");
                comm_center.call_service("SvrShowFBLoginFailed", z_param);
            end
        end;
    end;

    OnIFrameBeforeNavigate = function(pUILib, sWebUrl, dwCtrlID)
        TGPLog.LogI("VideoView", "OnIFrameBeforeNavigate url:" .. sWebUrl);
        -- TBrowserView.ShowWaitUI(true);
    end;

    OnIFrameDocumentComplete = function (pUILib, sWebUrl, dwCtrlID)
        TGPLog.LogI("VideoView", "OnIFrameDocumentComplete url:" .. sWebUrl);
        -- TBrowserView.ShowWaitUI(false);
    end;

    -- 打开网页
    OnOpenWeb = function(pUILib, sWebUrl, dwCtrlID)
        TGPLog.LogI("VideoView", "Open URL OK:" .. sWebUrl);

        if (TBrowserView.IsValidID(TBrowserView.dwViewID)) then
            TBrowserView.ShowWaitUI(false);   -- 隐藏等待界面
        else
            TGPLog.LogE("VideoView", "UI object not created.");
        end;

        if string.find(sWebUrl, EWebUIConst.FB_SUCCEESS_WEB_URL) ~= nil then
            if string.find(sWebUrl, "error_code") ~= nil then
                TGPLog.LogE("VideoView", "facebook login err, url="..sWebUrl);
                --TBrowserView.pWebView:Navigate(EWebUIConst.FB_FAILED_WEB_URL);
                comm_center.call_service("SvrShowFBLoginFailed", {});
                return;
            end

            local login_mgr =
            base_utility.get_component_adapter("ILogin_mgr",
                "ierd_tgp.login_mgr.GetLoginMgr();");
            local ret = login_mgr:login_with_facebook(sWebUrl);

            if ret == true then
                TBrowserView.BeforeClose();
                local   nViewID = TLoginView.pObjMain:GetControlID();
                    local   zParam = {};
                    zParam["nPageIdx"] = ELoginPage.lpLogining;
                    comm_center.call_service("Svr_SwitchLoginPage", zParam);
                    local zStatus = {};
                    zStatus["state"] = TStrHelper.GetString(EStrDefine.STR_FACEBOOK_AUTH_SUCC);
                    TLoginView.SetStatus(zStatus);
                return;
            else
                local   zParam = {};
                zParam["err_msg" ] = LoadStr("FACEBOOK_LOGIN_FAILED");
                zParam["err_code"] = 22;
                TLoginCtrl.ShowLoginError(zParam);
            end
        elseif sWebUrl == "https://www.facebook.com/" then
            TGPLog.LogE("VideoView", "redirect..");
            TBrowserView.StartWeb(TBrowserView.sFBWebURL);
            TBrowserView.ShowWaitUI(false);
        end

        -- 上报播放
        TBrowserView.NotifyOpen(1);
    end;

    -- 打开网页失败
    OnOpenFail = function(pUILib, sWebUrl, dwCtrlID)
        -- 打开失败
        TBrowserView.bHasErr = true;

        --[[
        -- 关闭视频
        if (TBrowserView.pWebView) then
            TBrowserView.pWebView:Stop();
            TBrowserView.pWebView:Show(false);
            TBrowserView.bIsOpen = false;
        end;

        -- 显示等待界面
        TBrowserView.ShowWaitUI(true);
        ]]
        -- 上报异常
        TBrowserView.NotifyError(EWebError.erOpenFail);

        -- 日志
        TGPLog.LogI("VideoView", "Open URL fail:" .. sWebUrl);
    end;

    -- JAVASCRIPT回调
    OnJsEvent = function(pUILib, sMethod, sParam, dwCtrlID)
        if "close" == sMethod then
            TBrowserView.OnClkClose(pUILib, 0);
        elseif "close_force" == sMethod then
            TBrowserView.BeforeClose();
        elseif "restart" == sMethod then
            comm_center.call_service("Svr_RestartWG", {});
        elseif "login_fail_redirect" == sMethod then
            comm_center.call_service("SvrShowFacebook", {});
        end;
    end;

    -- 网页Crash
    OnWebCrash = function(pUILib, dwCtrlID)
        -- 上报异常
        TBrowserView.NotifyError(EWebError.erWebCrash);

        -- 关闭视频界面
        TBrowserView.StopWeb();

        -- 显示等待界面
        TBrowserView.ShowWaitUI(false);

        TGPLog.LogI("VideoView", "Web browser crashed.");
    end;

    -- 创建播放器界面
    CreateUI = function(zParam)
        if (nil ~= TBrowserView.pWebView) and 
            TBrowserView.IsValidID(TBrowserView.dwViewID) then
            -- 检查窗口是否存在
            local     pUILib = ui_utility.uilib();

            if (nil ~= pUILib) then
                local     pDlg = pUILib:GetControlPtr(TBrowserView.dwViewID);

                if (nil ~= pDlg) then
                    return true;
                else
                    TGPLog.LogI("Browser", "Player window is already closed.");
                end;
            else
                TGPLog.LogE("Browser", "UILib object is null.");
            end;
        end;

        if not TBrowserView.IsValidID(TBrowserView.dwViewID) then
            TBrowserView.dwViewID = layout_mgr.restore_layout_multi("player.tpf");
        end;

        if TBrowserView.IsValidID(TBrowserView.dwViewID) then
            -- 监听窗体关闭消息
            ui_utility.setproperty_by_id(TBrowserView.dwViewID, "OnDialogClose", 
                                      "TBrowserView.OnDlgClose");

            -- 关闭按钮
            local   dwBtnID = ui_utility.get_ctrl_id_by_path(
                 TBrowserView.dwViewID, "TitleBarCtn\\btnClose");

            if (TBrowserView.IsValidID(dwBtnID)) then
                ui_utility.setproperty_by_id(dwBtnID, "OnClick", "TBrowserView.OnClkClose")
            else
                TGPLog.LogE("Browser", "Get close button fail.");
                return false;
            end;

            -- 最小化按钮
            dwBtnID = ui_utility.get_ctrl_id_by_path(TBrowserView.dwViewID, "TitleBarCtn\\btnMin");

            if (TBrowserView.IsValidID(dwBtnID)) then
                ui_utility.setproperty_by_id(dwBtnID, "OnClick", "TBrowserView.OnClkMin")
            else
                TGPLog.LogE("Browser", "Get min button fail.");
                return false;
            end;

            -- facebook登录需要隐藏左上角图标
            local dwTitle = ui_utility.get_ctrl_id_by_path(
                TBrowserView.dwViewID, "TitleBarCtn\\lblTitle");
            local dwIcon = ui_utility.get_ctrl_id_by_path(
                TBrowserView.dwViewID, "TitleBarCtn\\TitleIcon");
            if zParam ~= nil and zParam.HideIcon == true then
                ui_utility.setproperty_by_id(dwIcon, "Visible", "false");
            else
                ui_utility.setproperty_by_id(dwIcon, "Visible", "true");
            end

            -- 浏览器HOST
            TBrowserView.pWebHost = ui_utility.get_ctrl_ptr_by_path(TBrowserView.dwViewID,
                                                                    "uoBrowser");
            if (nil == TBrowserView.pWebHost) or (FALSE == TBrowserView.pWebHost:LoadContent()) then
                TGPLog.LogE("Browser", "Load web browser fail.");
                return false;
            end;

            -- 获取浏览器对象
            TBrowserView.pWebView = ui_utility.get_ctrl_ptr_by_path(
                TBrowserView.pWebHost:GetControlID(), "wbVideo");

            -- 导航
            if nil ~= TBrowserView.pWebView then
                -- 消息
                local   dwBrowser = TBrowserView.pWebView:GetControlID();

                ui_utility.setproperty_by_id(dwBrowser, "OnIFrameBeforeNavigate",
                                             "TBrowserView.OnIFrameBeforeNavigate");

                ui_utility.setproperty_by_id(dwBrowser, "OnIFrameDocumentComplete",
                                             "TBrowserView.OnIFrameDocumentComplete");

                ui_utility.setproperty_by_id(dwBrowser, "OnBeforeNavigate",
                                             "TBrowserView.OnStartOpen");

                ui_utility.setproperty_by_id(dwBrowser, "OnNavigateComplete",
                                             "TBrowserView.OnOpenWeb");

                ui_utility.setproperty_by_id(dwBrowser, "OnNavigateFailed",
                                             "TBrowserView.OnOpenFail");

                ui_utility.setproperty_by_id(dwBrowser, "OnJsCallback",
                                             "TBrowserView.OnJsEvent");

                ui_utility.setproperty_by_id(dwBrowser, "OnCrash",
                                             "TBrowserView.OnWebCrash");
            else
                TGPLog.LogE("Browser", "Get browser object fail.");
                return false;
            end;

            TBrowserView.pLoading = ui_utility.get_ctrl_ptr_by_path(
                TBrowserView.dwViewID, "pnlLoading");

            if nil ~= TBrowserView.pLoading then
                return true;
            else
                return false;
            end;
        else
            TGPLog.LogE("Browser", "Resotre layout fail.");
        end;

        return false;
    end;

    -- 卸载界面
    DestroyUI = function()
        TBrowserView.HideView();
    end;

    -- 显示加载中界面
    ShowWaitUI = function(bShow)
        if bShow then
            if (nil ~= TBrowserView.pLoading) then
                TBrowserView.pLoading:Show(TRUE);
            end;

            if (nil ~= TBrowserView.pWebHost) then
                TBrowserView.pWebHost:Show(FALSE);
            end;

            if (nil ~= TBrowserView.pWebView) then
                TBrowserView.pWebView:Show(false);
            end;

            TBrowserView.bIsOpen = false;
        else
            if (nil ~= TBrowserView.pLoading) then
                TBrowserView.pLoading:Show(FALSE);
            end;

            if (nil ~= TBrowserView.pWebHost) then
                TBrowserView.pWebHost:Show(TRUE);
            end;

            if (nil ~= TBrowserView.pWebView) then
                TBrowserView.pWebView:Show(true);
            end;

            TBrowserView.bIsOpen = true;
        end;
    end;

    -- 显示视频
    StartWeb = function(sWebUrl)
        if nil ~= TBrowserView.pWebView then
            TGPLog.LogI("Browser", "Open video:"..sWebUrl);

            local   sTemp = U8toCUIStr(sWebUrl);

            -- 导航到页面
            TBrowserView.bHasErr = false;
            TBrowserView.pWebView:Navigate(sTemp);

            -- 记录时间
            TBrowserView.dwStart = os.clock();
        else
            TGPLog.LogE("Browser", "Open video fail.");
        end;
    end;

    -- 关闭视频
    StopWeb = function()
        if nil ~= TBrowserView.pWebView then
            local   dwBrowser = TBrowserView.pWebView:GetControlID();

            if TBrowserView.IsValidID(dwBrowser) then
                ui_utility.setproperty_by_id(dwBrowser, "OnNavigateComplete","");
                ui_utility.setproperty_by_id(dwBrowser, "OnNavigateFailed", "");
                ui_utility.setproperty_by_id(dwBrowser, "OnJsCallback", "");
                ui_utility.setproperty_by_id(dwBrowser, "OnCrash", "");
            else
                TGPLog.LogE("TGPBoxView", "Get broswer fail.");
            end;

            TBrowserView.pWebView:Stop();
            TBrowserView.pWebView:Close();
            TBrowserView.pWebView = nil;

            -- 浏览器HOST
            if TBrowserView.pWebHost then
                TBrowserView.pWebHost:UnLoadContent();
            end;

            -- 通知关闭
            TBrowserView.NotifyClose(0);
        end;
    end;

    -- 控件ID是否有效
    IsValidID = function(dwCtrl)
        return (nil ~= dwCtrl) and (0 ~= dwCtrl);
    end;

    -- 关闭播放器
    OnClkClose = function(pUILib, dwCtrlID)
        if TBrowserView.canWebClose == true then
            if nil ~= TBrowserView.pWebView then
                local sFun = U8toCUIStr("web_close");
                local sArg = U8toCUIStr("");
                TBrowserView.pWebView:ExcecuteJS(sFun, sArg);
            end;
        else
            TBrowserView.BeforeClose();
        end;
    end;

    -- 窗体关闭
    OnDlgClose = function(pUILib, dwCtrlID, bClose)
        TBrowserView.BeforeClose();
    end;

    -- 关闭前通知浏览器
    BeforeClose = function()
        -- 通知浏览器
        if nil ~= TBrowserView.pWebView then
            local   sFun = U8toCUIStr("before_close");
            local   sArg = U8toCUIStr("");

            TBrowserView.pWebView:ExcecuteJS(sFun, sArg);
        end;

        -- 开启定时器
        local pTPFUI = base_utility.get_component_adapter("ITpf_ui",
                            "ierd_tgp.tpf_ui.GetTPFUI();");

        if nil ~= pTPFUI then
            pTPFUI:AddInterval("TBrowserView.OnTimerClose", EWebUIConst.nCloseWait, 0);
        else
            TGPLog.LogE("Browser", "Add interval fail.");
            TBrowserView.HideView();
        end;
    end;

    -- 定时关闭
    OnTimerClose = function(pUILib, nTimerID)
        -- 关闭定时器
        local pTPFUI = base_utility.get_component_adapter("ITpf_ui",
                            "ierd_tgp.tpf_ui.GetTPFUI();");

        if nil ~= pTPFUI then
            pTPFUI:RemoveInterval("TBrowserView.OnTimerClose", 0);
        else
            TGPLog.LogE("Browser", "Add interval fail.");
        end;

        TBrowserView.HideView();
    end;

    -- 最小化
    OnClkMin = function(pUILib, dwCtrlID)
        local     pCtrl = pUILib:GetControlPtr(TBrowserView.dwViewID);
        local     pDlg  = tolua.cast(pCtrl, "Tenio::ITDialog");

        if nil ~= pDlg then
            pDlg:Minimize();
        else
            TGPLog.LogE("Browser", "Get window object fail.");
        end;
    end;

    -- 通知打开
    NotifyOpen = function(nErrCode)
        if (nil ~= TBrowserView.sOnOpen) then
            TBrowserView.DoCallBack(TBrowserView.sOnOpen, nErrCode);
        end;
    end;

    -- 关闭通知
    NotifyClose = function(nErrCode)
        if (nil ~= TBrowserView.sOnClose) then
            TBrowserView.DoCallBack(TBrowserView.sOnClose, nErrCode);
        end;
    end;

    -- 通知错误
    NotifyError = function(nErrCode)
        if (nil ~= TBrowserView.sOnError) then
            TBrowserView.DoCallBack(TBrowserView.sOnError, nErrCode);
        end;
    end;

    -- 回调事件
    DoCallBack = function(sEvent, nParam)
        local   sCode = "local  nTemp =" .. tostring(nParam) .. ";"..
                        sEvent .. "(nTemp);"
        local   pCode = loadstring(sCode);

        if (nil ~= pCode) then
            pCode();
        else
            TGPLog.LogE("Browser", "Load event fail.");
        end;
    end;

    -- Private
    pLoading = nil;
    pWebHost = nil;
    pWebView = nil;
    dwViewID = 0;
    bHasErr  = false;
    bIsOpen  = false;
    canWebClose = false;

    -- 事件通知
    sOnError = nil;
    sOnOpen  = nil;
    sOnClose = nil;

};